﻿using ScFramework.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 此类只能当EntityManager模块存在时使用
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class EntityInstanceMgr<T1,T2> : LogicModuleBase, IRestrictUpdater where T1:SComponent where T2:SComponent
{
    protected Dictionary<UInt32, T1> _compsDic1;
    protected Dictionary<UInt32, T2> _compsDic2;
    public override void Init(SubmoduleBase p, object args = null)
    {
        base.Init(p, args);
        Debug.Assert(typeof(T1) != typeof(T2));
        _compsDic1 = new Dictionary<uint, T1>();
        _compsDic2 = new Dictionary<uint, T2>();
    }
    protected T1 Get1ByEid(UInt16 id)
    {
        try
        {
            foreach(var x in _compsDic1)
            {
                if (x.Key.left() == id)
                {
                    return x.Value;
                }
            }
            return null;

        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
    protected T2 Get2ByEid(UInt16 id)
    {
        try
        {
            foreach (var x in _compsDic2)
            {
                if (x.Key.left() == id)
                {
                    return x.Value;
                }
            }
            return null;

        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
    protected T1 Get1(UInt32 id)
    {
        try
        {
            return _compsDic1[id];

        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
    protected T2 Get2(UInt32 id)
    {
        try
        {
            return _compsDic2[id];

        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
    public virtual void OnCreated1(List<T1> comp)
    {

    }
    public virtual void OnDeleted1(List<T1> comp)
    {

    }
    public virtual void OnCreated2(List<T2> comp)
    {

    }
    public virtual void OnDeleted2(List<T2> comp)
    {

    }
    public virtual void OnValueChanged1(T1 com, ushort vid, object v)
    {

    }
    public virtual void OnValueChanged2(T2 com, ushort vid, object v)
    {

    }
    void AddToDic<T>(List<Entity> es,Dictionary<UInt32,T>dic,Action<List<T>>OnCreated)where T:SComponent
    {
        ///先加入RigidUnion实例
        var cs = es.FindAll(s => s.GetComponent<T>() != null);
        var nlist = new List<T>();
        foreach (var x in cs)
        {
            var list = x.GetComponents<T>();
            foreach (var v in list)
            {
                Debug.Assert(dic.ContainsKey(v.SData.CompIdentity) == false);
                dic[v.SData.CompIdentity] = v;
                Debug.Assert(typeof(T).IsAssignableFrom(v.GetType()));
                nlist.Add(v as T);
            }
        }
                OnCreated(nlist);
            
    }
    List<ValueChangeArgs> valueChangeQue = new List<ValueChangeArgs>();
    public virtual void UpdateBeforeFunc()
    {
    
    }
    [RegisterEvent(EntityDataEvent.ValueChanged)]
    protected void OnValueChanged(ValueChangeArgs args)
    {
        valueChangeQue.Add(args);
        /*
        var tp1 = Get1(args.EntityID.combine(args.ValueID.left()));
        if (tp1 != null)
        {
            OnValueChanged1(tp1, args.ValueID.right(), args.Value);
        }
        var tp2 = Get2(args.EntityID.combine(args.ValueID.left()));
        if (tp2 != null)
        {
            OnValueChanged2(tp2, args.ValueID.right(), args.Value);
        }*/

    }
    /// <summary>
    /// 当实例被创建时
    /// </summary>
    /// <param name="es"></param>
    [RegisterEvent(PhysicsProcessEvent.InstancesCreated)]
    protected void OnInstancesCreated(List<Entity> es)
    {
        AddToDic<T1>(es, _compsDic1,OnCreated1);
        AddToDic<T2>(es, _compsDic2,OnCreated2);

    }
    /// <summary>
    /// 当实例被删除时,移除字典中相应的实例
    /// </summary>
    /// <param name="ids"></param>
    [RegisterEvent(PhysicsProcessEvent.InstancesToDelete)]
    protected void OnInstancesDeleted(List<UInt16> ids)
    {
        List<UInt32> removeList1 = new List<uint>();
        List<UInt32> removeList2 = new List<uint>();

        foreach (var x in ids)
        {
            foreach (var key in _compsDic1.Keys)
            {
                if (key.left() == x)
                {
                    removeList1.Add(key);
                }
            }
            foreach (var key in _compsDic2.Keys)
            {
                if (key.left() == x)
                {
                    removeList2.Add(key);
                }
            }

        }
        OnDeleted1(removeList1.ConvertAll(s=>_compsDic1[s]));
      
        foreach(var x in removeList1)
        {
            _compsDic1.Remove(x);
        }
            OnDeleted2(removeList2.ConvertAll(s=>_compsDic2[s]));
        foreach (var x in removeList2)
        {
            _compsDic2.Remove(x);
        }
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
        _compsDic1.Clear();
        _compsDic2.Clear();
    }

    public virtual void UpdateBeforePhysicSimu()
    {
    }

    public void UpdateAfterSyncInstance()
    {
        foreach (var args in valueChangeQue)
        {
            var tp1 = Get1(args.EntityID.combine(args.ValueID.left()));
            if (tp1 != null)
            {
                OnValueChanged1(tp1, args.ValueID.right(), args.Value);
            }
            var tp2 = Get2(args.EntityID.combine(args.ValueID.left()));
            if (tp2 != null)
            {
                OnValueChanged2(tp2, args.ValueID.right(), args.Value);
            }
        }
        valueChangeQue.Clear();
    }
}
/// <summary>
/// 此类只能当EntityManager模块存在时使用
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class EntityInstanceMgr<T> : LogicModuleBase where T : SComponent
{
    protected Dictionary<UInt32, T> _compsDic;
    public override void Init(SubmoduleBase p, object args = null)
    {
        base.Init(p, args);
        _compsDic = new Dictionary<uint, T>();
    }
    protected T Get(UInt32 id)
    {
        try
        {
            return _compsDic[id];

        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
    public virtual void OnCreated(T comp)
    {

    }
    public virtual void OnDeleted(T comp)
    {

    }
    public virtual void OnValueChanged(T com, ushort vid, object v)
    {

    }
    void AddToDic(List<Entity> es)
    {
        ///先加入RigidUnion实例
        var cs = es.FindAll(s => s.GetComponent<T>() != null);
        foreach (var x in cs)
        {
            var list = x.GetComponents<T>();
            foreach (var v in list)
            {
                Debug.Assert(_compsDic.ContainsKey(v.SData.CompIdentity) == false);
                _compsDic[v.SData.CompIdentity] = v;
                OnCreated(v);
            }
        }

    }
    [RegisterEvent(EntityDataEvent.ValueChanged)]
    protected void OnValueChanged(ValueChangeArgs args)
    {

        var tp = Get(args.EntityID.combine(args.ValueID.left()));
        if (tp != null)
        {
            OnValueChanged(tp, args.ValueID.right(), args.Value);
        }
    }
    /// <summary>
    /// 当实例被创建时
    /// </summary>
    /// <param name="es"></param>
    [RegisterEvent(PhysicsProcessEvent.InstancesCreated)]
    protected void OnInstancesCreated(List<Entity> es)
    {
        AddToDic(es);

    }
    /// <summary>
    /// 当实例被删除时,移除字典中相应的实例
    /// </summary>
    /// <param name="ids"></param>
    [RegisterEvent(PhysicsProcessEvent.InstancesToDelete)]
    protected void OnInstancesDeleted(List<UInt16> ids)
    {
        List<UInt32> removeList = new List<uint>();

        foreach (var x in ids)
        {
            foreach (var key in _compsDic.Keys)
            {
                if (key.left() == x)
                {
                    removeList.Add(key);
                }
            }
        }
        foreach (var x in removeList)
        {
            OnDeleted(_compsDic[x]);
            _compsDic.Remove(x);
        }
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
        _compsDic.Clear();
    }
}
